Categories
Modern JavaScript

Best of Modern JavaScript — Well-Known Symbols

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at new OOP features in JavaScript.

How to use __proto__?

To get the prototype of an object, we use Object.getPrototypeOf .

To create an object with a given prototype, we can use Object.create .

Object.setPrototypeOf is deprecate and it prevents optimizations in many browsers.

__proto__ can be used to get and set the prototype of an object.

Enumerability

The for-in loop traverses the string keys of an own and inherited enumerable properties.

Object.keys returns the string keys of an enumerable own properties.

JSON.stringify only stringified enumerable own properties and string keys.

In ES6, Object.assign only copies enumerable own string and symbol properties.

There’re many non-enumerable properties in a JavaScript object.

All prototype properties of built-in classes are non-enumerable.

For instance, if we have:

const desc = Object.getOwnPropertyDescriptor.bind(Array);
console.log(desc(Object.prototype, 'toString').enumerable)

We get the property descriptors in the Array.prototype.toString method.

And we get the enumerable property, and it’ll log false .

Marking Properties as not to be Copied

We can mark a property not to be copied if we mark the property as being enumerable.

For instance, we can write:

const obj = Object.defineProperty({}, 'foo', {
  value: 'bar',
  enumerable: false
});

We set the enumerable property to false so that it won’t be picked up by Object.assign or the spread operator.

**Object.assign()**

Object.assign can be used to merge object sources into the target.

All own enumerable properties from the sources will be copied to the target.

It doesn’t consider inherited properties.

Hiding Own Properties from JSON.stringify()

Hiding own properties from JSON.stringify can be done by making properties non-enumerable.

This will make JSON.stringify skip the properties.

We can also specify the toJSON method to return the object we want to stringify.

For example, we can write:

const obj = {
  foo: 'bar',
  toJSON() {
    return {
      bar: 'baz'
    };
  },
};

console.log(JSON.stringify(obj))

Then the console log will log {“bar”:”baz”} .

Customizing Basic Language Operations via Well-Known Symbols

We can customize basic language operations with well-known symbols.

The Symbol.hasInstance method lets an object customize the behavior of the instanceof operator.

Symbol.toPrimitive is a method that lets us customize how it’s converted to a primitive value.

The Symbol.toStringTag method lets us call Object.prototype.toString to compute the string description of an object.

Symbol.unscopables lets us hide some properties from the with statement.

obj instanceof C works by doing some checks.

If C isn’t an object, then it throws a TypeError .

If the method exists, then it calls C[Symbol.hasInstance](obj) .

It coerces the result to boolean and returns it.

Otherwise, it computes and returns the result according to the regular algorithm by checking for scalability, C.prototype in the prototype chain of obj , etc.

The only method in the standard library that has Symbol.hasInstance is Function.prototype .

We can check whether a value in an object by writing:

const ObjType = {
  [Symbol.hasInstance](value) {
    return (value !== null &&
      (typeof value === 'object' ||
        typeof value === 'function'));
  }
};

We create our own ObjType object with the Symbol.hasInstance method.

It takes the value we want to check.

Then it checks whether it’s not bull , the type of value is 'object' or 'function' .

Then we can use it by writing:

{} instanceof ObjType

which returns true .

Conclusion

Enumerabnility of objects can be changed and checked.

Also, we can change the behavior or instanceof and other operators by overriding methods with well-known symbols.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *